﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;

namespace FooFun.DataElements.Dtos
{
    public abstract class DataElement : IDataElement, IConvertible
    {
        public DataElement()
        {

        }

        public DataElement(object obj)
        {
            this.Value = obj;
        }

        public override bool Equals(object obj)
        {
            if (obj == null)
            {
                return false;
            }
            if (this.IsEmpty)
            {
                return false;
            }

            if (this.Value != null)
            {
                if (obj is IDataElement)
                {
                    IDataElement de = obj as IDataElement;

                    return this.Value.Equals(de.Value);
                }
                else
                {
                    return this.Value.Equals(obj);
                }
            }
            return false;
        }

        public override int GetHashCode()
        {
            if (this.Value != null)
            {
                return this.Value.GetHashCode();
            }
            else
            {
                throw new DataElementException("该DataElement为空");
            }
        }

        public override string ToString()
        {
            if (this.Value != null)
            {
                return this.Value.ToString();
            }
            else
            {
                return string.Empty;
            }
        }

        #region IDataElement 成员

        public virtual object Value
        {
            get
            {
                //string str = this.GetType().Name + "无法取值";

                //throw new DataElementException(str);
                return null;
            }
            set
            {
                string str = this.GetType().Name + "无法设值";

                throw new DataElementException(str);
            }
        }

        public virtual IDataElement this[string key]
        {
            get
            {
                string str = "取值失败：" + this.GetType().Name + "无法从" + key
                    + "键取值";

                return new EmptyDataElement(str, this);
            }
            set
            {
                string str = "设值失败：" + this.GetType().Name + "无法在" + key
                    + "键设值";
                throw new DataElementException(str);
            }
        }

        public virtual IDataElement this[int index]
        {
            get
            {
                string str = "取值失败：" + this.GetType().Name + "无法从" + index
                    + "数字索引取值";
                return new EmptyDataElement(str, this);
            }
            set
            {
                string str = "设值失败：" + this.GetType().Name + "无法在" + index
                    + "数字索引设值";
                throw new DataElementException(str);
            }
        }

        public virtual IEnumerable GetKeys()
        {
            string str = "取键集合失败：" + this.GetType().Name + "无法取到键集合";
            throw new DataElementException(str);
        }

        IDataElement parent;
        public virtual IDataElement Parent
        {
            get
            {
                if (parent == null)
                {
                    return new EmptyDataElement();
                }
                return parent;
            }
            set
            {
                parent = value;
            }
        }

        public virtual bool IsEmpty
        {
            get { return true; }
        }

        public virtual IEnumerator GetEnumerator()
        {
            if (this.IsEmpty)
            {
                yield break;
            }
            else
            {
                yield return this;
            }
        }

        public virtual IDataElement Add(IDataElement de)
        {
            string str = "添加元素失败：" + this.GetType().Name + "无法添加类型为" + de.GetType().Name + "的元素";
            throw new DataElementException(str);
        }

        #endregion

        #region IConvertible 成员

        public virtual TypeCode GetTypeCode()
        {
            return TypeCode.Empty;
        }

        public bool ToBoolean(IFormatProvider provider)
        {
            if (this.Value is IConvertible)
            {
                IConvertible conv = (IConvertible)this.Value;
                return conv.ToBoolean(provider);
            }

            throw new DataElementException("无法转换");
        }

        public byte ToByte(IFormatProvider provider)
        {
            if (this.Value is IConvertible)
            {
                IConvertible conv = (IConvertible)this.Value;
                return conv.ToByte(provider);
            }

            throw new DataElementException("无法转换");
        }

        public char ToChar(IFormatProvider provider)
        {
            if (this.Value is IConvertible)
            {
                IConvertible conv = (IConvertible)this.Value;
                return conv.ToChar(provider);
            }

            throw new DataElementException("无法转换");
        }

        public DateTime ToDateTime(IFormatProvider provider)
        {
            if (this.Value is IConvertible)
            {
                IConvertible conv = (IConvertible)this.Value;
                return conv.ToDateTime(provider);
            }

            throw new DataElementException("无法转换");
        }

        public decimal ToDecimal(IFormatProvider provider)
        {
            if (this.Value is IConvertible)
            {
                IConvertible conv = (IConvertible)this.Value;
                return conv.ToDecimal(provider);
            }

            throw new DataElementException("无法转换");
        }

        public double ToDouble(IFormatProvider provider)
        {
            if (this.Value is IConvertible)
            {
                IConvertible conv = (IConvertible)this.Value;
                return conv.ToDouble(provider);
            }

            throw new DataElementException("无法转换");
        }

        public short ToInt16(IFormatProvider provider)
        {
            if (this.Value is IConvertible)
            {
                IConvertible conv = (IConvertible)this.Value;
                return conv.ToInt16(provider);
            }

            throw new DataElementException("无法转换");
        }

        public int ToInt32(IFormatProvider provider)
        {
            if (this.Value is IConvertible)
            {
                IConvertible conv = (IConvertible)this.Value;
                return conv.ToInt32(provider);
            }

            throw new DataElementException("无法转换");
        }

        public long ToInt64(IFormatProvider provider)
        {
            if (this.Value is IConvertible)
            {
                IConvertible conv = (IConvertible)this.Value;
                return conv.ToInt64(provider);
            }

            throw new DataElementException("无法转换");
        }

        public sbyte ToSByte(IFormatProvider provider)
        {
            if (this.Value is IConvertible)
            {
                IConvertible conv = (IConvertible)this.Value;
                return conv.ToSByte(provider);
            }

            throw new DataElementException("无法转换");
        }

        public float ToSingle(IFormatProvider provider)
        {
            if (this.Value is IConvertible)
            {
                IConvertible conv = (IConvertible)this.Value;
                return conv.ToSingle(provider);
            }

            throw new DataElementException("无法转换");
        }

        public string ToString(IFormatProvider provider)
        {
            if (this.IsEmpty)
            {
                return string.Empty;
            }
            if (this.Value is IConvertible)
            {
                IConvertible conv = (IConvertible)this.Value;
                return conv.ToString(provider);
            }

            //throw new DataElementException("无法转换");
            return string.Empty;
        }

        public object ToType(Type conversionType, IFormatProvider provider)
        {
            if (this.Value is IConvertible)
            {
                IConvertible conv = (IConvertible)this.Value;
                return conv.ToType(conversionType, provider);
            }

            throw new DataElementException("无法转换");
        }

        public ushort ToUInt16(IFormatProvider provider)
        {
            if (this.Value is IConvertible)
            {
                IConvertible conv = (IConvertible)this.Value;
                return conv.ToUInt16(provider);
            }

            throw new DataElementException("无法转换");
        }

        public uint ToUInt32(IFormatProvider provider)
        {
            if (this.Value is IConvertible)
            {
                IConvertible conv = (IConvertible)this.Value;
                return conv.ToUInt32(provider);
            }

            throw new DataElementException("无法转换");
        }

        public ulong ToUInt64(IFormatProvider provider)
        {
            if (this.Value is IConvertible)
            {
                IConvertible conv = (IConvertible)this.Value;
                return conv.ToUInt64(provider);
            }

            throw new DataElementException("无法转换");
        }

        #endregion
    }
}
